class YBC_SWS_SRA_LOGIN definition
  public
  inheriting from CL_ICF_SYSTEM_LOGIN
  create public .

*"* public components of class YBC_SWS_SRA_LOGIN
*"* do not include other source files here!!!
public section.

  constants CO_SAP_SL_DUMMY type STRING value '__sap-sl__dummy' ##NO_TEXT.
  constants CO_SAP_HASH type STRING value 'sap-hash' ##NO_TEXT.
  class-data GV_NEW_ESCAPE_API type ABAP_BOOL value abap_true ##NO_TEXT.

  class-methods ESCAPE_HTML
    importing
      !IV_UNESCAPED type STRING
    returning
      value(RV_ESCAPED) type STRING .
  methods HTM_RESTORE_HASH
    returning
      value(RV_HTML) type STRING .

  methods HTM_CHANGE_PASSWD
    redefinition .
  methods HTM_LOGIN
    redefinition .
  methods HTM_MESSAGE_BOX
    redefinition .
  methods HTM_SESSION_QUERY
    redefinition .
  methods HTM_SYSTEM_MESSAGE
    redefinition .
protected section.
*"* protected components of class YBC_SWS_SRA_LOGIN
*"* do not include other source files here!!!

  types:
    thihttpnvp TYPE HASHED TABLE OF ihttpnvp WITH UNIQUE KEY name .

  data M_HASH type STRING .
  type-pools ABAP .
  data M_LANGU_RTL type ABAP_BOOL value abap_false. "#EC NOTEXT .
  constants CO_STYLE_DISPLAY_HIDDEN type STRING value 'style="visibility: hidden;"'. "#EC NOTEXT
  constants CO_STYLE_DISPLAY_NONE type STRING value 'style="display: none;"'. "#EC NOTEXT
  constants CO_CONTEXT_CHANGEPWD type STRING value 'changepwd'. "#EC NOTEXT
  constants CO_CONTEXT_CHANGEPWD_CANCEL type STRING value 'changepwd_cancel'. "#EC NOTEXT
  constants CO_CONTEXT_CHANGEPWD_END type STRING value 'changepwd_end'. "#EC NOTEXT
  constants CO_CONTEXT_MSG type STRING value 'msg'. "#EC NOTEXT
  constants CO_CONTEXT_LOGIN type STRING value 'login'. "#EC NOTEXT

  class-methods LEGACY_ESCAPE_HTML
    importing
      !IV_UNESCAPED type STRING
    returning
      value(RV_ESCAPED) type STRING .
  methods INIT_CSS_THEME_LINK
    importing
      !IV_CSS_LIB type STRING .
  methods GET_SEVERITY_PROP_NAME
    importing
      !IV_PROP_NAME type STRING
      !IV_SEVERITY type I
    returning
      value(RV_PROP_NAME) type STRING .
  methods GET_PROPERTY
    importing
      !IV_NAME type STRING
    returning
      value(RV_VALUE) type STRING .
  methods INIT_DEFAULT_PROPERTIES
    importing
      !IV_CONTEXT type STRING .
  methods INIT_HIDDEN_FIELDS
    importing
      !IV_HIDDEN_FIELDS type STRING
      !IV_CONTEXT type STRING .
  methods INIT_SYSTEM_PROPERTIES
    importing
      !IV_CONTEXT type STRING
      !IV_JAVASCRIPT type STRING
      !IV_HIDDEN_FIELDS type STRING .
  methods LOAD_APP_PROPERTIES .
  methods PROCESS_TEMPLATE
    importing
      !IV_TEMPLATE type STRING
    returning
      value(RV_RESULT) type STRING .
  methods SET_PROPERTY
    importing
      !IV_NAME type STRING
      !IV_VALUE type STRING .
  methods INIT_JAVASCRIPT
    importing
      !IV_JAVASCRIPT type STRING
      !IV_CONTEXT type STRING .

  methods BUILD_HIDDEN_FIELDS
    redefinition .
  methods WRITE_RESPONSE
    redefinition .
private section.
*"* private components of class YBC_SWS_SRA_LOGIN
*"* do not include other source files here!!!

  data M_SRA_PROPERTIES type THIHTTPNVP .

  methods INIT_NATIVE_LANGUAGES .
  methods INIT_LANGU_RTL .
  methods INIT_HASH .
  methods SET_SEVERITY_SYS_PROP
    importing
      !IV_PROP_NAME type STRING
      !IV_SEVERITY type I .
  methods GET_CONTEXT_JAVASCRIPT
    importing
      !IV_CONTEXT type STRING
    returning
      value(RV_JAVASCRIPT) type STRING .
  methods GET_FOLDER
    importing
      !I_PATH type STRING
    returning
      value(RV_FOLDER) type STRING .
  methods GET_LANGUAGES
    returning
      value(RV_LANGUAGES) type STRING .
  methods GET_MESSAGES
    returning
      value(RV_MESSAGES) type BSPMSG .
  methods INIT_CSS_STYLE .
  methods INIT_CSS_IE8_STYLE .
  methods LOAD_MIME_REPO_TEXT_FILE
    importing
      !I_URL type CSEQUENCE
    returning
      value(RV_TEXT) type STRING .
  methods PARSE_APP_PROPERTIES
    importing
      !IV_APP_PROPERTIES type STRING .
ENDCLASS.



CLASS YBC_SWS_SRA_LOGIN IMPLEMENTATION.


METHOD BUILD_HIDDEN_FIELDS.
  DATA ls_field TYPE ihttpnvp.

  hidden_fields = super->build_hidden_fields( for_login = for_login for_application = for_application ).

  init_hash( ).
  ls_field-name = co_sap_hash.
  ls_field-value = m_hash.
  APPEND ls_field TO hidden_fields.

ENDMETHOD.


METHOD ESCAPE_HTML.
  IF gv_new_escape_api = abap_true.
    TRY.
        CALL METHOD ('CL_ABAP_DYN_PRG')=>escape_xss_xml_html
          EXPORTING
            val = iv_unescaped
          RECEIVING
            out = rv_escaped.
        " Restore </> and <space>
        REPLACE ALL OCCURRENCES OF '&#x2f;' IN rv_escaped WITH '/'.
        REPLACE ALL OCCURRENCES OF '&#x20;' IN rv_escaped WITH ` `.
        REPLACE ALL OCCURRENCES OF '&#x2b;' IN rv_escaped WITH '+'.
      CATCH cx_sy_dyn_call_illegal_method.
        gv_new_escape_api = abap_false.
        rv_escaped = legacy_escape_html( iv_unescaped ).
      CATCH cx_sy_dyn_call_illegal_class.
        gv_new_escape_api = abap_false.
        rv_escaped = legacy_escape_html( iv_unescaped ).
    ENDTRY.
  ELSE.
    rv_escaped = legacy_escape_html( iv_unescaped ).
  ENDIF.
ENDMETHOD.


METHOD GET_CONTEXT_JAVASCRIPT.
  DATA lv_select_lang TYPE c LENGTH 5.
  DATA lv_select_client TYPE c LENGTH 5.
  DATA lv_available_languages TYPE string.
  DATA lv_languages TYPE string.
  DATA lv_app_languages TYPE string.
  DATA lv_text_direction TYPE c LENGTH 3.
  DATA lv_texts TYPE string.
  DATA lv_error_user_initial TYPE string.
  DATA lv_error_pwd_initial TYPE string.
  DATA lv_error_client_initial TYPE string.
  DATA lv_style_submit_disabled TYPE string.
  DATA lv_style_changepwd_hidden TYPE string.
  DATA lv_style_confirmpwd_error TYPE string.

  " Languages
  IF m_langu_rtl = abap_true.
    lv_text_direction = 'rtl'.
  ELSE.
    lv_text_direction = 'ltr'.
  ENDIF.

  IF c_login_params-langu_visible = abap_true.
    lv_select_lang = 'true'.
    lv_available_languages = get_languages( ).
    CONCATENATE '{ lang: "' m_language '", direction: "' lv_text_direction '", available: ' lv_available_languages '};' INTO lv_languages. "#EC NOTEXT
  ELSE.
    lv_select_lang = 'false'.
    CONCATENATE '{ lang: "' m_language '", direction: "' lv_text_direction '", available: [] };' INTO lv_languages. "#EC NOTEXT
  ENDIF.

  " Application may restrict the list of allowed languages
  lv_app_languages = get_property( 'application_languages' ).
  IF lv_app_languages IS NOT INITIAL.
    CONCATENATE '  sraLogin.languages.application = "' lv_app_languages '";' co_crlf INTO lv_app_languages. "#EC NOTEXT
  ENDIF.

  " Error texts
  lv_error_user_initial = get_property( 'text_error_user_initial' ).
  lv_error_pwd_initial = get_property( 'text_error_pwd_initial' ).
  lv_error_client_initial = get_property( 'text_error_client_initial' ).
  CONCATENATE '{ error_user_initial: " ' lv_error_user_initial
    '", error_pwd_initial: "' lv_error_pwd_initial
    '", error_client_initial: "' lv_error_client_initial '" }'
  INTO lv_texts. "#EC NOTEXT

  " Options
  IF c_login_params-client_visible = abap_true.
    lv_select_client = 'true'.
  ELSE.
    lv_select_client = 'false'.
  ENDIF.

  " Styles
  lv_style_confirmpwd_error = get_property( 'style_confirmpwd_error' ).

  " Output
  CONCATENATE
    '  var sraLogin = {};' co_crlf
    '  sraLogin.context = "' iv_context '";' co_crlf
    '  sraLogin.languages = ' lv_languages co_crlf lv_app_languages
    '  sraLogin.texts = ' lv_texts co_crlf
    '  sraLogin.options = { selectLanguage: ' lv_select_lang ', selectClient: ' lv_select_client ' };' co_crlf
    '  sraLogin.styles = { submit_disabled: "' lv_style_submit_disabled '", changePassword_hidden: "' lv_style_changepwd_hidden '", confirmPassword_error: "' lv_style_confirmpwd_error '" };' co_crlf
  INTO rv_javascript. "#EC NOTEXT

ENDMETHOD.


METHOD GET_FOLDER.
  FIND REGEX '(.*)/[^/]*' IN i_path SUBMATCHES rv_folder.
ENDMETHOD.


METHOD GET_LANGUAGES.
  DATA lv_separator TYPE c VALUE ''.
  FIELD-SYMBOLS <fs_lang> TYPE ihttpnvp.

  rv_languages = '[ '.
  LOOP AT m_languages ASSIGNING <fs_lang>.
    CONCATENATE rv_languages lv_separator '{ value: "' <fs_lang>-name '", label: "' <fs_lang>-value '" }' INTO rv_languages. "#EC NOTEXT
    lv_separator = ','.
  ENDLOOP.
  CONCATENATE rv_languages ' ]' INTO rv_languages.
ENDMETHOD.


METHOD GET_MESSAGES.
  DATA message TYPE string.
  DATA lv_severity TYPE i.
  DATA lv_separator TYPE c LENGTH 4 VALUE ''.

  FIELD-SYMBOLS <fs_msg> TYPE bspmsg.

  TYPES:
    BEGIN OF keystype,
        message   TYPE string,
        index     TYPE syindex,
    END OF keystype.

  DATA keys TYPE HASHED TABLE OF keystype WITH UNIQUE KEY message.
  DATA key LIKE LINE OF keys.

  IF m_logmessages IS NOT INITIAL.
    LOOP AT m_logmessages ASSIGNING <fs_msg>.
      CLEAR key.
      key-message = <fs_msg>-message.
      key-index = sy-tabix.
      INSERT key INTO TABLE keys.
      IF sy-subrc <> 0.
        CONTINUE.
      ENDIF.

      IF lv_severity IS INITIAL.
        lv_severity = <fs_msg>-severity.
      ELSE.
        CASE <fs_msg>-severity.
          WHEN 4. "ifur_d2=>messagetype_stop.
            lv_severity = 1. "ifur_d2=>messagetype_error.
          WHEN 1. "ifur_d2=>messagetype_error.
            lv_severity = 1. "ifur_d2=>messagetype_error.
          WHEN 2. "ifur_d2=>messagetype_warning.
            lv_severity = 1. "ifur_d2=>messagetype_error.
          WHEN 7. "ifur_d2=>messagetype_text.
            IF lv_severity = 3. "ifur_d2=>messagetype_ok.
              lv_severity = 7. "ifur_d2=>messagetype_text.
            ENDIF.
        ENDCASE.
      ENDIF.

      message = escape_html( <fs_msg>-message ).
      CONCATENATE rv_messages-message lv_separator message co_crlf INTO rv_messages-message.
      lv_separator = '<br>'.
    ENDLOOP.
    rv_messages-severity = lv_severity.
  ENDIF.
ENDMETHOD.


METHOD GET_PROPERTY.
  FIELD-SYMBOLS <fs_nvp> TYPE ihttpnvp.

  READ TABLE m_sra_properties WITH TABLE KEY name = iv_name ASSIGNING <fs_nvp>.
  IF <fs_nvp> IS ASSIGNED.
    rv_value = <fs_nvp>-value.
  ELSE.
    log__msg( msg = 'property undefined: [&A&] = ' a = iv_name ). "#EC NOTEXT
  ENDIF.
ENDMETHOD.


METHOD GET_SEVERITY_PROP_NAME.
  DATA lv_suffix TYPE c LENGTH 10.

  CASE iv_severity.
    WHEN 1. "ifur_d2=>messagetype_error.
      lv_suffix = '_error'.
    WHEN 7. "ifur_d2=>messagetype_text.
      lv_suffix = '_info'.
    WHEN 3. "ifur_d2=>messagetype_ok.
      lv_suffix = '_ok'.
    WHEN OTHERS.
      lv_suffix = '_info'.
  ENDCASE.
  CONCATENATE iv_prop_name lv_suffix INTO rv_prop_name.
ENDMETHOD.


METHOD HTM_CHANGE_PASSWD.
  DATA lv_template_name TYPE string.
  DATA lv_template_file TYPE string.
  DATA lv_template TYPE string.
  DATA lv_context TYPE string.

  log__method( name = '/ui2/cl_sra_login->htm_change_password' ).

  CASE m_change_pw_step.
    WHEN co_change_pw_change.
      lv_context = co_context_changepwd.
      lv_template_name = 'template_changepwd'.
    WHEN co_change_pw_was_changed.
      lv_context = co_context_changepwd_end.
      lv_template_name = 'template_changepwd_end'.
    WHEN co_change_pw_not_possible.
      lv_context = co_context_changepwd_cancel.
      lv_template_name = 'template_changepwd_cancel'.
  ENDCASE.

  init_default_properties( lv_context ). " overridable properties
  load_app_properties( ). " application specific override
  init_system_properties( iv_context = lv_context iv_javascript = iv_javascript iv_hidden_fields = iv_hidden_fields ).

  lv_template_file = get_property( lv_template_name ).
  lv_template = load_mime_repo_text_file( lv_template_file ).

  rv_html = process_template( lv_template ).

  log__end_method( ).
ENDMETHOD.


METHOD HTM_LOGIN.
  DATA lv_template_file TYPE string.
  DATA lv_template TYPE string.

  log__method( name = '/ui2/cl_sra_login->htm_login' ).

  init_default_properties( co_context_login ). " overridable properties
  load_app_properties( ). " application specific override
  init_system_properties( iv_context = co_context_login iv_javascript = iv_javascript iv_hidden_fields = iv_hidden_fields ).

  lv_template_file = get_property( 'template_login' ).
  lv_template = load_mime_repo_text_file( lv_template_file ).

  rv_html = process_template( lv_template ).

  log__end_method( ).
ENDMETHOD.


METHOD HTM_MESSAGE_BOX.
  DATA lv_template_file TYPE string.
  DATA lv_template TYPE string.

  log__method( name = '/ui2/cl_sra_login->htm_message_box' ).

  init_default_properties( co_context_msg ). " overridable properties
  load_app_properties( ). " application specific override
  init_system_properties( iv_context = co_context_msg iv_javascript = iv_javascript iv_hidden_fields = iv_hidden_fields ).

  lv_template_file = get_property( 'template_msg' ).
  lv_template = load_mime_repo_text_file( lv_template_file ).

  rv_html = process_template( lv_template ).

  log__end_method( ).

ENDMETHOD.


METHOD HTM_RESTORE_HASH.
  DATA lv_hash TYPE string.
  DATA lv_template TYPE string.
  " Not necessary as hash input parameter is validated to contain only harmless base64 characters
  " Yet SLIN is not able to understand this :-)
  lv_hash = escape_html( m_hash ).

  lv_template = load_mime_repo_text_file( '/sap/public/bc/ui2/logon/template_hash.html' ).
  set_property( iv_name = 'sys_form_hash' iv_value = lv_hash ).
  set_property( iv_name = 'sys_form_action' iv_value = m_sap_application ).
  rv_html = process_template( lv_template ).
ENDMETHOD.


METHOD HTM_SESSION_QUERY.

  log__method( name = '/ui2/cl_sra_login->htm_session_query' ).

  CONCATENATE
    '<!DOCTYPE html>' co_crlf
    '<html>' co_crlf
    '  <head><title>HTM_SESSION_QUERY</title></head>' co_crlf
    '  <body>Not implemented</body>' co_crlf '</html>' co_crlf
  INTO rv_html.  "#EC NOTEXT

  log__end_method( ).
ENDMETHOD.


METHOD HTM_SYSTEM_MESSAGE.

  log__method( name = '/ui2/cl_sra_login->htm_system_message' ).

  CONCATENATE
     '<!DOCTYPE html>' co_crlf
     '<html>' co_crlf
     '  <head><title>HTM_SYSTEM_MESSAGE</title></head>' co_crlf
     '  <body>Not implemented</body>' co_crlf
     '</html>' co_crlf
   INTO rv_html. "#EC NOTEXT

  log__end_method( ).
ENDMETHOD.


METHOD INIT_CSS_IE8_STYLE.
  DATA lv_template_name TYPE string.
  DATA lv_template TYPE string.
  DATA lv_css TYPE string.
  DATA lv_custom_css TYPE string.
  DATA lv_style TYPE string.

  lv_template_name = get_property( 'template_css_ie8' ).
  lv_template = load_mime_repo_text_file( lv_template_name ).
  lv_css = process_template( lv_template ).

  lv_template_name = get_property( 'custom_css_ie8' ).
  IF lv_template_name IS NOT INITIAL.
    lv_template = load_mime_repo_text_file( lv_template_name ).
    lv_custom_css = process_template( lv_template ).
  ENDIF.

  CONCATENATE
    '<style>' co_crlf
    lv_css
    lv_custom_css
    '</style>' co_crlf
  INTO lv_style.

  set_property( iv_name = 'css_ie8_style' iv_value = lv_style ).

ENDMETHOD.


METHOD INIT_CSS_STYLE.
  DATA lv_template_name TYPE string.
  DATA lv_template TYPE string.
  DATA lv_css TYPE string.
  DATA lv_custom_css TYPE string.
  DATA lv_style TYPE string.

  lv_template_name = get_property( 'template_css' ).
  lv_template = load_mime_repo_text_file( lv_template_name ).
  lv_css = process_template( lv_template ).

  lv_template_name = get_property( 'custom_css' ).
  IF lv_template_name IS NOT INITIAL.
    lv_template = load_mime_repo_text_file( lv_template_name ).
    lv_custom_css = process_template( lv_template ).
  ENDIF.

  CONCATENATE
    '<style>' co_crlf
    lv_css
    lv_custom_css
    '</style>' co_crlf
  INTO lv_style.

  set_property( iv_name = 'css_style' iv_value = lv_style ).

ENDMETHOD.


METHOD INIT_CSS_THEME_LINK.
  DATA lv_ui5_theme TYPE string.
  DATA lv_thd_theme TYPE string.
  DATA lv_thd_client TYPE string.
  DATA lv_theme_link TYPE string.

  lv_thd_theme = get_property( 'thd_theme' ).

  IF lv_thd_theme IS INITIAL.
    " Load themes through regular UI5 handler
    lv_ui5_theme = get_property( 'ui5_theme' ).
    CONCATENATE
      ' <link rel="stylesheet" href="/sap/public/bc/ui2/logon/themes-v1/' lv_ui5_theme iv_css_lib '" />'
    INTO lv_theme_link.
  ELSE.
    " Load themes through Theme handler
    lv_thd_client = get_property( 'thd_client' ).
    IF lv_thd_client IS INITIAL.
      lv_thd_client = m_sap_client.
    ENDIF.
    CONCATENATE
      ' <link rel="stylesheet" href="/sap/public/bc/themes/~client-' lv_thd_client
      '/UI5/sap/fiori/themes/' lv_thd_theme iv_css_lib '" />'
    INTO lv_theme_link.
  ENDIF.

  set_property( iv_name = 'css_theme_link' iv_value = lv_theme_link ).
ENDMETHOD.


METHOD INIT_DEFAULT_PROPERTIES.
  log__method( name = '/ui2/cl_sra_login->init_default_properties' msg = 'iv_context=[&A&]' a = iv_context ).

  init_langu_rtl( ).

  " Common properties
  set_property( iv_name = 'header_visible' iv_value = 'false' ). "#EC NOTEXT
  set_property( iv_name = 'img_favicon' iv_value = '/sap/public/bc/ui2/logon/img/favicon.ico' ).
  set_property( iv_name = 'img_logo' iv_value = '/sap/public/bc/ui2/logon/img/sap_logo.png' ).
  "  set_property( iv_name = 'img_logo' iv_value = '/sap/public/bc/ui2/YBC_SWS/logo.png' ).
  set_property( iv_name = 'img_logo_width' iv_value = '64' ).

  "set_property( iv_name = 'img_background' iv_value = '/sap/public/bc/ui2/logon/img/login_background.jpg' ).
  "set_property( iv_name = 'img_background_mobile' iv_value = '/sap/public/bc/ui2/logon/img/login_background_mobile.jpg' ).
  "set_property( iv_name = 'img_background_mobile_land' iv_value = '/sap/public/bc/ui2/logon/img/login_background_mobile_land.jpg' ).

  set_property( iv_name = 'img_background' iv_value = '/sap/public/bc/ui2/YBC_SWS/bg_md.png' ).
  set_property( iv_name = 'img_background_mobile' iv_value = '/sap/public/bc/ui2/YBC_SWS/bg_sm1.png' ).
  set_property( iv_name = 'img_background_mobile_land' iv_value = '/sap/public/bc/ui2/YBC_SWS/bg_sm1.png' ).

  set_property( iv_name = 'img_background_ie8' iv_value = '/sap/public/bc/ui2/logon/img/login_background_ie8.jpg' ).
  set_property( iv_name = 'label_copyright' iv_value = m_txt_copyright ).
  set_property( iv_name = 'label_user' iv_value = m_txt_label_user ).
  set_property( iv_name = 'script_included' iv_value = '/sap/public/bc/ui2/logon/login.js' ).
  set_property( iv_name = 'style_confirmpwd_error' iv_value = 'sapUiSraTextError' ).
  set_property( iv_name = 'template_css' iv_value = '/sap/public/bc/ui2/logon/template_css.css' ).
  set_property( iv_name = 'template_css_ie8' iv_value = '/sap/public/bc/ui2/logon/template_css_ie8.css' ).
  set_property( iv_name = 'ui5_theme' iv_value = 'sap_bluecrystal' ).
  set_property( iv_name = 'text_error_user_initial' iv_value = m_txt_login_error_user_initial ).
  set_property( iv_name = 'text_error_pwd_initial' iv_value = m_txt_login_error_pw_initial ).
  set_property( iv_name = 'text_error_client_initial' iv_value = m_txt_login_error_clnt_init ).
  set_property( iv_name = 'button_focus_color' iv_value = '#d0d0d0' ).
  set_property( iv_name = 'button_submit_focus_color' iv_value = '#007cc0' ).
  set_property( iv_name = 'message_error_background_color' iv_value = '#fad4d4' ).
  set_property( iv_name = 'message_error_border_color' iv_value = '#e52929' ).
  set_property( iv_name = 'message_error_focus_color' iv_value = '#dab4b4' ).
  set_property( iv_name = 'message_info_background_color' iv_value = '#f7f7f7' ).
  set_property( iv_name = 'message_info_focus_color' iv_value = '#d0d0d0' ).

  CASE iv_context.
    WHEN co_context_login.
      set_property( iv_name = 'label_button_login' iv_value = m_txt_button_login ).
      set_property( iv_name = 'label_button_login_loading' iv_value = m_txt_button_login ).
      set_property( iv_name = 'label_change_password' iv_value = m_txt_button_login_change_pwd ).
      set_property( iv_name = 'label_client' iv_value = m_txt_label_client ).
      set_property( iv_name = 'label_language' iv_value = m_txt_label_language ).
      set_property( iv_name = 'label_password' iv_value = m_txt_label_password ).
      set_property( iv_name = 'label_title_login' iv_value = m_txt_title_login ).
      set_property( iv_name = 'template_login' iv_value = '/sap/public/bc/ui2/logon/template_login.html' ).

    WHEN co_context_changepwd.
      set_property( iv_name = 'label_button_cancel' iv_value = m_txt_button_cancel ).
      set_property( iv_name = 'label_button_change' iv_value = m_txt_button_change_passwd ).
      set_property( iv_name = 'label_confirm_password' iv_value = m_txt_label_new_password2 ).
      set_property( iv_name = 'label_current_password' iv_value = m_txt_label_current_password ).
      set_property( iv_name = 'label_new_password' iv_value = m_txt_label_new_password ).
      set_property( iv_name = 'label_title_changepwd' iv_value = m_txt_title_change_password ).
      set_property( iv_name = 'template_changepwd' iv_value = '/sap/public/bc/ui2/logon/template_changepwd.html' ).

    WHEN co_context_changepwd_end.
      set_property( iv_name = 'label_button_continue' iv_value = m_txt_button_continue ).
      set_property( iv_name = 'label_title_changepwd_end' iv_value = m_txt_title_change_password ).
      set_property( iv_name = 'template_changepwd_end' iv_value = '/sap/public/bc/ui2/logon/template_changepwd_end.html' ).

    WHEN co_context_changepwd_cancel.
      set_property( iv_name = 'label_button_changepwd_not_possible' iv_value = m_txt_button_cancel ).
      set_property( iv_name = 'label_title_changepwd_not_possible' iv_value = m_txt_title_change_password ).
      set_property( iv_name = 'template_changepwd_cancel' iv_value = '/sap/public/bc/ui2/logon/template_changepwd_cancel.html' ).

    WHEN co_context_msg.
      set_property( iv_name = 'script_msg_selfsubmit_error' iv_value = '0' ).
      set_property( iv_name = 'script_msg_selfsubmit_info' iv_value = '0' ).
      set_property( iv_name = 'script_msg_selfsubmit_ok' iv_value = '5000' ).
      set_property( iv_name = 'label_msg_class_error' iv_value = 'sapUiSraMessageError' ). "#EC NOTEXT
      set_property( iv_name = 'label_msg_class_info' iv_value = 'sapUiSraMessageInfo' ).
      set_property( iv_name = 'label_msg_class_ok' iv_value = 'sapUiSraMessageInfo' ).
      set_property( iv_name = 'button_msg_class_error' iv_value = 'sapMBtnDefault' ). "#EC NOTEXT
      set_property( iv_name = 'button_msg_class_info' iv_value = 'sapMBtnDefault' ). "#EC NOTEXT
      set_property( iv_name = 'button_msg_class_ok' iv_value = 'sapMBtnEmphasized' ). "#EC NOTEXT
      set_property( iv_name = 'label_button_msg_error' iv_value = m_txt_button_cancel ).
      set_property( iv_name = 'label_button_msg_info' iv_value = m_txt_button_continue ).
      set_property( iv_name = 'label_button_msg_ok' iv_value = m_txt_button_continue ).
      set_property( iv_name = 'label_title_msg_error' iv_value = m_txt_title_error ).
      set_property( iv_name = 'label_title_msg_info' iv_value = m_txt_title_login_information ).
      set_property( iv_name = 'label_title_msg_ok' iv_value = m_txt_title_login ).
      set_property( iv_name = 'template_msg' iv_value = '/sap/public/bc/ui2/logon/template_msg.html' ).
  ENDCASE.

  log__end_method( ).
ENDMETHOD.


METHOD INIT_HASH.
  DATA lv_hash TYPE string.
  lv_hash = m_server->request->get_form_field( co_sap_hash ).
  IF ( NOT lv_hash IS INITIAL ) AND ( lv_hash <> '' ).
    " sap-hash parameter must be the base64 representation of the hash in UTF-8 encoding without padding
    "   => check that it contains only harmless base64 characters
    FIND REGEX '[^0-9A-Za-z+/]' IN lv_hash. "#EC NOTEXT
    IF sy-subrc = 4.
      m_hash = lv_hash.
    ENDIF.
  ENDIF.
ENDMETHOD.


METHOD INIT_HIDDEN_FIELDS.
  DATA lv_hidden_fields TYPE string.
  DATA lv_user TYPE string.

  lv_hidden_fields = iv_hidden_fields.

  IF iv_context = co_context_login AND c_login_params-langu_visible = abap_true.
    CONCATENATE
      lv_hidden_fields co_crlf
      '<input id="LANGUAGE_PARAM_VALUE" type="hidden" name="' co_sap_language '" value="' m_language '">' "#EC NOTEXT
    INTO lv_hidden_fields.
  ENDIF.

  IF iv_context = co_context_changepwd and m_user_parameter = 'sap-alias'.
    " ICF does not sanitize m_user parameter
    lv_user = escape_html( m_user ).
    CONCATENATE
      lv_hidden_fields co_crlf
      '<input type="hidden" name="sap-alias" value="' lv_user '">' "#EC NOTEXT
    INTO lv_hidden_fields.
  ENDIF.

  set_property( iv_name = 'sys_form_hidden_fields' iv_value = lv_hidden_fields ).

ENDMETHOD.


METHOD INIT_JAVASCRIPT.
  DATA lv_javascript TYPE string.
  DATA lv_context_js TYPE string.

  lv_context_js = get_context_javascript( iv_context ).
  CONCATENATE '<script>' iv_javascript co_crlf lv_context_js '</script>' INTO lv_javascript.

  set_property( iv_name = 'sys_script_generated' iv_value = lv_javascript ).

ENDMETHOD.


method INIT_LANGU_RTL.
  IF m_langu CA cl_i18n_bidi=>rtl_languages.
    m_langu_rtl = abap_true.
  ELSE.
    m_langu_rtl = abap_false.
  ENDIF.
endmethod.


METHOD INIT_NATIVE_LANGUAGES.
  " Load current supported languages for installation
  DATA: lv_syslanguages    TYPE scplangss,
        lv_syslanguage     TYPE c,
        lt_cl              TYPE t002,
        lt_clt             TYPE t002t,
        ls_nv              LIKE LINE OF m_languages.

  CLEAR m_languages.

  CALL FUNCTION 'SCP_ALLOWED_LANGUAGES'
    IMPORTING
      languages = lv_syslanguages.

  WHILE lv_syslanguages IS NOT INITIAL.
    lv_syslanguage = lv_syslanguages(1).

    SELECT SINGLE * FROM t002  INTO lt_cl  WHERE spras = lv_syslanguage.
    SELECT SINGLE * FROM t002t INTO lt_clt WHERE spras = lt_cl-spras
                                           AND   sprsl = lt_cl-spras.
    IF sy-subrc = 0.
      ls_nv-name  = lt_cl-laiso.
      ls_nv-value = lt_clt-sptxt.
      APPEND ls_nv TO me->m_languages.
    ENDIF.
    SHIFT lv_syslanguages LEFT.
  ENDWHILE.

  APPEND INITIAL LINE TO me->m_languages.
  SORT me->m_languages BY value.

ENDMETHOD.


METHOD INIT_SYSTEM_PROPERTIES.
  DATA lv_messages TYPE bspmsg.
  DATA lv_prop_val TYPE string.
  DATA lv_css_lib TYPE string.
  DATA lv_input_count TYPE i VALUE 2.
  DATA lv_height_class TYPE string.
  DATA lv_user_length TYPE string.
  DATA lv_user_name TYPE string.

  log__method( name = '/ui2/cl_sra_login->init_system_properties' msg = 'iv_context=[&A&]' a = iv_context ). "#EC NOTEXT

  " Common properties
  set_property( iv_name = 'at' iv_value = '@' ).
  set_property( iv_name = 'media' iv_value = '@media' ).
  set_property( iv_name = 'sys_form_action' iv_value = m_sap_application ).
  set_property( iv_name = 'sys_icf_cookie_check' iv_value = co_js_cookie_check ).
  set_property( iv_name = 'sys_form_input_processing' iv_value = co_event_input_processing ).

  IF m_langu_rtl = abap_true.
    lv_css_lib = '/library-RTL.css'.                        "#EC NOTEXT
    set_property( iv_name = 'sys_text_direction' iv_value = 'rtl' ). "#EC NOTEXT
    set_property( iv_name = 'sys_css_library' iv_value = 'library-RTL.css' ). "#EC NOTEXT
  ELSE.
    lv_css_lib = '/library.css'.
    set_property( iv_name = 'sys_text_direction' iv_value = 'ltr' ). "#EC NOTEXT
    set_property( iv_name = 'sys_css_library' iv_value = 'library.css' ). "#EC NOTEXT
  ENDIF.

  IF get_property( 'css_theme_link' ) IS INITIAL.
    init_css_theme_link( lv_css_lib ).
  ENDIF.

  IF get_property( 'css_style' ) IS INITIAL.
    init_css_style( ).
  ENDIF.

  IF get_property( 'css_ie8_style' ) IS INITIAL.
    init_css_ie8_style( ).
  ENDIF.


  lv_prop_val = get_property( 'header_visible' ).
  IF lv_prop_val <> 'true'.
    set_property( iv_name = 'sys_header_state' iv_value = co_style_display_none ).
  ELSE.
    set_property( iv_name = 'sys_header_state' iv_value = '' ).
  ENDIF.

  lv_messages = get_messages( ).
  IF lv_messages IS INITIAL.
    set_property( iv_name = 'sys_messages_state' iv_value = co_style_display_hidden ).
    set_property( iv_name = 'sys_messages_text' iv_value = '' ).
  ELSE.
    lv_input_count = lv_input_count + 1.
    set_property( iv_name = 'sys_messages_state' iv_value = '' ).
    set_property( iv_name = 'sys_messages_text' iv_value = lv_messages-message ).
  ENDIF.

  CASE iv_context.
    WHEN co_context_login.
      init_native_languages( ).

      " Login properties
      set_property( iv_name = 'sys_form_default_client' iv_value = m_sap_client ).
      set_property( iv_name = 'sys_form_event_changepwd' iv_value = co_event_change_password ).
      set_property( iv_name = 'sys_form_event_login' iv_value = co_event_login ).
      set_property( iv_name = 'sys_form_name_login' iv_value = co_form_login ).
      set_property( iv_name = 'sys_form_param_client' iv_value = co_sap_client ).
      set_property( iv_name = 'sys_form_param_password' iv_value = co_sap_password ).
      set_property( iv_name = 'sys_form_param_user' iv_value = m_user_parameter ).
      lv_user_length = m_user_length.

      set_property( iv_name = 'sys_form_user_maxlen' iv_value = lv_user_length ).

      set_property( iv_name = 'sys_form_submit_login' iv_value = co_js_submit_login ).

      IF c_login_params-langu_visible = abap_true.
        lv_input_count = lv_input_count + 1.
      ELSE.
        set_property( iv_name = 'sys_form_lang_state' iv_value = co_style_display_none ).
      ENDIF.
      IF c_login_params-client_visible = abap_true.
        lv_input_count = lv_input_count + 1.
      ELSE.
        set_property( iv_name = 'sys_form_client_state' iv_value = co_style_display_none ).
      ENDIF.

      IF c_login_params-autocomplete = abap_true.
        set_property( iv_name = 'sys_autocomplete' iv_value = 'on' ).
      ELSE.
        set_property( iv_name = 'sys_autocomplete' iv_value = 'off' ).
      ENDIF.

      lv_height_class = lv_input_count.
      CONCATENATE 'sapUiSraLoginHeight' lv_height_class INTO lv_height_class.
      set_property( iv_name = 'sys_login_height_class' iv_value = lv_height_class ).

    WHEN co_context_changepwd.
      " Change password property
      set_property( iv_name = 'sys_form_event_cancel_changepwd' iv_value = co_event_cancel_password ).
      set_property( iv_name = 'sys_form_event_do_changepwd' iv_value = co_event_do_change_password ).
      set_property( iv_name = 'sys_form_name_changepwd' iv_value = co_form_change_password ).
      set_property( iv_name = 'sys_form_param_confirm_password' iv_value = co_password_repeat ).
      set_property( iv_name = 'sys_form_param_current_password' iv_value = co_password ).
      set_property( iv_name = 'sys_form_param_new_password' iv_value = co_password_new ).
      set_property( iv_name = 'sys_form_submit_changepwd' iv_value = co_js_submit_change_password ).
      lv_user_name = m_user.
      IF m_user_parameter = 'sap-alias'.
        TRANSLATE lv_user_name TO LOWER CASE.
        set_property( iv_name = 'sys_chpwd_userlabel_state' iv_value = co_style_display_none ).
      ENDIF.
      set_property( iv_name = 'sys_form_user_name' iv_value = lv_user_name ).
      set_property( iv_name = 'sys_login_height_class' iv_value = 'sapUiSraLoginHeight4' ). "#EC NOTEXT

      lv_height_class = lv_input_count + 2.
      CONCATENATE 'sapUiSraLoginHeight' lv_height_class INTO lv_height_class.
      set_property( iv_name = 'sys_login_height_class' iv_value = lv_height_class ).

      IF m_change_pw_can_cancel = abap_true.
        set_property( iv_name = 'sys_changepwd_button_row_class' iv_value = 'sapUiSraLoginButtonBlock' ). "#EC NOTEXT
        set_property( iv_name = 'sys_changepwd_cancel_state' iv_value = '' ).
      ELSE.
        set_property( iv_name = 'sys_changepwd_button_row_class' iv_value = 'sapUiSraSingleButtonBlock' ). "#EC NOTEXT
        set_property( iv_name = 'sys_changepwd_cancel_state' iv_value = co_style_display_none ).
      ENDIF.

    WHEN co_context_changepwd_end.
      set_property( iv_name = 'sys_form_event_continue_changepwd' iv_value = co_event_continue_password ).
      set_property( iv_name = 'sys_form_name_changepwd' iv_value = co_form_change_password ).
      set_property( iv_name = 'sys_form_submit_changepwd' iv_value = co_js_submit_change_password ).
      IF get_property( 'label_changepwd_end' ) IS INITIAL.
        set_property( iv_name = 'label_changepwd_end' iv_value = lv_messages-message ).
      ENDIF.

    WHEN co_context_changepwd_cancel.
      set_property( iv_name = 'sys_form_event_cancel_changepwd' iv_value = co_event_cancel_password ).
      set_property( iv_name = 'sys_form_name_changepwd' iv_value = co_form_change_password ).
      set_property( iv_name = 'sys_form_submit_changepwd' iv_value = co_js_submit_change_password ).

    WHEN co_context_msg.
      set_property( iv_name = 'sys_form_event_continue_changepwd' iv_value = co_event_continue_password ).
      set_property( iv_name = 'sys_form_name_changepwd' iv_value = co_form_change_password ).
      set_property( iv_name = 'sys_form_submit_changepwd' iv_value = co_js_submit_change_password ).
      set_severity_sys_prop( iv_prop_name = 'script_msg_selfsubmit' iv_severity = lv_messages-severity ).
      set_severity_sys_prop( iv_prop_name = 'label_title_msg' iv_severity = lv_messages-severity ).
      set_severity_sys_prop( iv_prop_name = 'label_button_msg' iv_severity = lv_messages-severity ).
      set_severity_sys_prop( iv_prop_name = 'label_msg_class' iv_severity = lv_messages-severity ).
      set_severity_sys_prop( iv_prop_name = 'button_msg_class' iv_severity = lv_messages-severity ).

  ENDCASE.

  " Generated content
  init_javascript( iv_javascript = iv_javascript iv_context = iv_context ).
  init_hidden_fields( iv_hidden_fields = iv_hidden_fields iv_context = iv_context ).

  log__end_method( ).
ENDMETHOD.


METHOD LEGACY_ESCAPE_HTML.
  CALL METHOD ('CL_HTTP_UTILITY')=>escape_html
    EXPORTING
      unescaped = iv_unescaped
    RECEIVING
      escaped   = rv_escaped.
ENDMETHOD.


METHOD LOAD_APP_PROPERTIES.
  DATA:
    lv_path TYPE string,
    lv_length TYPE i,
    lv_mime_file TYPE string,
    lv_app_properties TYPE string.

  log__method( name = '/ui2/cl_sra_login->load_app_properties' ).

  lv_path = m_sap_application.
  REPLACE REGEX '^/sap\([^)]*\)' IN lv_path WITH '/sap'.
  REPLACE REGEX '^/sap/bc/ui5_ui5' IN lv_path WITH '/sap/bc/bsp'.

  DO.
    lv_path = get_folder( lv_path ).
    lv_length = STRLEN( lv_path ).
    IF lv_length <= 1.
      EXIT.
    ENDIF.

    CONCATENATE lv_path '/login.properties' INTO lv_mime_file.
    lv_app_properties = load_mime_repo_text_file( lv_mime_file ).
    IF lv_app_properties IS NOT INITIAL.
      log__msg( msg = 'loading application properties: [&A&]' A = lv_mime_file ). "#EC NOTEXT
      parse_app_properties( lv_app_properties ).

      CONCATENATE lv_path '/login_' m_language '.properties' INTO lv_mime_file.
      lv_app_properties = load_mime_repo_text_file( lv_mime_file ).
      IF lv_app_properties IS NOT INITIAL.
        log__msg( msg = 'loading application localized properties: [&A&]' A = lv_mime_file ). "#EC NOTEXT
        parse_app_properties( lv_app_properties ).
      ENDIF.

      EXIT.
    ENDIF.
  ENDDO.

  log__end_method( ).
ENDMETHOD.


METHOD LOAD_MIME_REPO_TEXT_FILE.
  DATA:
        mime_repository TYPE REF TO if_mr_api,
        mime_xstring TYPE xstring,
        l_conv TYPE REF TO cl_abap_conv_in_ce.

  log__method( name = '/ui2/cl_sra_login->load_mime_repo_text_file' msg = 'i_url=[&A&]' a = i_url ).

  mime_repository ?= cl_mime_repository_api=>get_api( ).

  CALL METHOD mime_repository->get
    EXPORTING
      i_url              = i_url
      i_check_authority  = abap_false
    IMPORTING
      e_content          = mime_xstring
    EXCEPTIONS
      parameter_missing  = 1
      error_occured      = 2
      not_found          = 3
      permission_failure = 4
      OTHERS             = 5.

  IF sy-subrc = 0.
    l_conv = cl_abap_conv_in_ce=>create( ).
    l_conv->convert( EXPORTING input = mime_xstring  IMPORTING data = rv_text ).
  ELSE.
    log__msg( msg = 'Not found.' ). "#EC NOTEXT
  ENDIF.

  log__end_method( ).

ENDMETHOD.


METHOD PARSE_APP_PROPERTIES.
  DATA:
      lv_length TYPE i,
      itab TYPE TABLE OF string,
      prop_name TYPE string,
      prop_val TYPE string.

  FIELD-SYMBOLS <fs_prop> TYPE string.

  SPLIT iv_app_properties AT co_crlf INTO TABLE itab.
  LOOP AT itab ASSIGNING <fs_prop>.
    lv_length = STRLEN( <fs_prop> ).
    IF lv_length = 0.
      CONTINUE.
    ENDIF.

    FIND REGEX '\s*#' IN <fs_prop>. " search for comment lines
    IF sy-subrc = 0.
      CONTINUE.
    ENDIF.

    FIND REGEX '\s*(\w+)\s*=\s?(.*)' IN <fs_prop> SUBMATCHES prop_name prop_val.
    IF sy-subrc = 0.
      set_property( iv_name = prop_name iv_value = prop_val ).
    ENDIF.
  ENDLOOP.
ENDMETHOD.


METHOD PROCESS_TEMPLATE.
  DATA lv_offset TYPE i.
  DATA lv_match_offset TYPE i.
  DATA lv_match_length TYPE i.
  DATA lv_before_length TYPE i.
  DATA lv_token TYPE string.
  DATA lv_prop_val TYPE string.

  log__method( name = '/ui2/cl_sra_login->process_template' ).

  lv_match_length = STRLEN( iv_template ).
  IF lv_match_length < 1.
    RETURN.
  ENDIF.
  lv_offset = 0.
  DO.
    FIND REGEX '@(Html\.Raw\(|\w+|@)' IN SECTION OFFSET lv_offset OF iv_template
      MATCH OFFSET lv_match_offset
      MATCH LENGTH lv_match_length
      SUBMATCHES lv_token.
    IF sy-subrc = 0.
      lv_before_length = lv_match_offset - lv_offset.
      IF lv_before_length > 0.
        CONCATENATE rv_result iv_template+lv_offset(lv_before_length) INTO rv_result RESPECTING BLANKS.
      ENDIF.
      CASE lv_token.
        WHEN 'Html.Raw('.
          lv_offset = lv_match_offset + lv_match_length.
          FIND REGEX '\s*(\w+)\s*\)' IN SECTION OFFSET lv_offset OF iv_template
            MATCH OFFSET lv_match_offset
            MATCH LENGTH lv_match_length
            SUBMATCHES lv_token.
          IF sy-subrc = 0.
            lv_prop_val = get_property( lv_token ).
            CONCATENATE rv_result lv_prop_val INTO rv_result RESPECTING BLANKS.
          ENDIF.
        WHEN '@'.
          CONCATENATE rv_result '@' INTO rv_result RESPECTING BLANKS.
        WHEN OTHERS.
          lv_prop_val = get_property( lv_token ).
          lv_prop_val = escape_html( lv_prop_val ).
          CONCATENATE rv_result lv_prop_val INTO rv_result RESPECTING BLANKS.
      ENDCASE.
      lv_offset = lv_match_offset + lv_match_length.
    ELSE.
      CONCATENATE rv_result iv_template+lv_offset INTO rv_result RESPECTING BLANKS.
      EXIT.
    ENDIF.
  ENDDO.

  log__end_method( ).
ENDMETHOD.


METHOD SET_PROPERTY.
  DATA wa TYPE ihttpnvp.
  wa-name = iv_name.
  wa-value = iv_value.
  DELETE TABLE m_sra_properties WITH TABLE KEY name = wa-name.
  INSERT wa INTO TABLE m_sra_properties.
ENDMETHOD.


METHOD SET_SEVERITY_SYS_PROP.
  DATA lv_prop_name TYPE string.
  DATA lv_sys_prop_name TYPE string.
  DATA lv_prop_val TYPE string.

  lv_prop_name = get_severity_prop_name( iv_prop_name = iv_prop_name iv_severity = iv_severity ).
  lv_prop_val = get_property( lv_prop_name ).
  CONCATENATE 'sys_' iv_prop_name INTO lv_sys_prop_name.
  set_property( iv_name = lv_sys_prop_name iv_value = lv_prop_val ).

ENDMETHOD.


METHOD WRITE_RESPONSE.
  DATA lv_html TYPE string.
  DATA lo_response TYPE REF TO if_http_response.
  DATA lv_override TYPE abap_bool VALUE abap_false.

  init_hash( ).
  CASE iv_page.
    WHEN co_event_system_message OR co_event_session_query.
      " System message and session query are not implemented, return relay page restoring initial target location
      lv_override = abap_true.
    WHEN co_event_post_redirect.
      IF m_hash IS NOT INITIAL.
        lv_override = abap_true.
      ENDIF.
  ENDCASE.

  lo_response = m_server->response.
  IF lv_override = abap_true.
    lv_html = htm_restore_hash( ).
    lo_response->set_status( code = 200 reason = if_http_status=>reason_200 ).
    lo_response->set_cdata( lv_html ).
    lo_response->set_header_field( name = 'Expires' value = '0' ). "#EC NOTEXT
    lo_response->set_header_field( name = 'Pragma' value = 'no-cache' ). "#EC NOTEXT

    DATA: l_user_agent_type TYPE i.
    m_server->request->get_user_agent( IMPORTING user_agent_type = l_user_agent_type ).
    IF m_server->ssl_active = 1 AND l_user_agent_type = ihttp_user_agent_ie AND c_login_params-autocomplete = abap_true.
      m_server->response->set_header_field( name  = 'Cache-Control' value = 'must-revalidate, private, max-age=0' ). "#EC NOTEXT
    ELSE.
      m_server->response->set_header_field( name  = 'Cache-Control' value = 'no-cache, no-store, private' ). "#EC NOTEXT
    ENDIF.
  ELSE.
    super->write_response( iv_page ).
  ENDIF.
ENDMETHOD.
ENDCLASS.
